Last Update: 2019-01-31 00:09:44
GitHub Repository: sv4u/goalie-and-skater-heat-maps
In the NHL, players have their sweet-spots. For skaters, it can be the top of a certain circle, or right in-front of the net. For goalies, it could be where their vision is best and where they have the best angle to cut down a shot. All players have these sweet-spots, but it is difficult to analytically say where they are. By using shot location data, we can determine these locations and create models show where goalies and skaters need improvement and where they succeed.
Before we jump in, let’s clean up our R environment and also load in some libraries we will be using.
rm(list = ls())
library(purrr)
library(ggplot2)
To start, we need to read in our data. Our data is formatted nicely in CSV format. We have data from the, 2015-2016 season, 2016-2017 season, 2017-2018 season, and 2018-2019 season (up to 1/30/19). This data was downloaded from MoneyPuck. Let’s first start by loading in all three seasons of data:
data.2015 = read.csv("data/2015.csv")
data.2016 = read.csv("data/2016.csv")
data.2017 = read.csv("data/2017.csv")
data.2018 = read.csv("data/2018.csv")
Note: this will take a relatively long time to compute as the datasets are large. Each dataset contains all shot data (including playoffs).
We’ll only look at regular season data. The playoffs in the NHL are a beast of their own.
get.regular.season = function(data) {
subset(data, isPlayoffGame == 0)
}
season.2015 = get.regular.season(data.2015)
season.2016 = get.regular.season(data.2016)
season.2017 = get.regular.season(data.2017)
season.2018 = get.regular.season(data.2018)
Now that we have our data, we can remove extraneous columns. Here is a table of what columns we are keeping, and what we are renaming them to:
| Old Column | New Column |
|---|---|
| xCordAdjusted | x |
| yCordAdjusted | y |
| goal | goal |
| shotAngleAdjusted | angle |
| goalieNameForShot | goalie_name |
| shooterName | skater_name |
| game_id | game |
Now, here is the R code to do this subsetting of the original dataset.
get.helpful.data = function(data) {
data.frame(x = data$xCordAdjusted,
y = data$yCordAdjusted,
goal = data$goal,
angle = data$shotAngleAdjusted,
goalie_name = data$goalieNameForShot,
skater_name = data$shooterName,
game = data$game_id)
}
analysis.2015 = get.helpful.data(season.2015)
analysis.2016 = get.helpful.data(season.2016)
analysis.2017 = get.helpful.data(season.2017)
analysis.2018 = get.helpful.data(season.2018)
Now, we have all the data we need.
From our data, we can calculate some very important statistics like the following:
Additionally, we can break up our data by game. There are some generic functions we can write to help for both goalies and skaters. Let’s write them now!
get.goal.percent = function(data) {
shots = length(data$goal)
temp = subset(data, goal == 1)
goals = length(temp$goal)
goals / shots
}
get.save.percent = function(data) {
shots = length(data$goal)
temp = subset(data, goal == 1)
goals = length(temp$goal)
(shots - goals) / shots
}
get.shots.per.goal = function(data) {
shots = length(data$goal)
temp = subset(data, goal == 1)
goals = length(temp$goal)
shots / goals
}
Note: when using
get.shots.per.goal, if there were no goals scored, R will handle the division by zero by returning infinity. This will be problematic when graphing data. I am still working on a good solution to this problem. Earlier, I used 200 as a substitute value. However, 200 still skews graphs, which is unideal.
get.games = function(data) {
unique(data$game)
}
get.single.game = function(data, game_id) {
subset(data, game == game_id)
}
get.all.games = function(data) {
games = get.games(data)
Map(function(x) get.single.game(data, x), games)
}
Now, we can create our game by game statistic functions:
get.game.goal.percent = function(data) {
gameframe = get.all.games(data)
games.gp = map(gameframe, function(x) get.goal.percent(x))
unlist(games.gp, use.names = FALSE)
}
get.game.save.percent = function(data) {
gameframe = get.all.games(data)
games.sp = map(gameframe, function(x) get.save.percent(x))
unlist(games.sp, use.names = FALSE)
}
get.game.shots.per.goal = function(data) {
gameframe = get.all.games(data)
games.spg = map(gameframe, function(x) get.shots.per.goal(x))
unlist(games.spg, use.names = FALSE)
}
Also, we’ll need a function to get match-ups between a specific goalie and skater. Let’s write that here, instead of in our goalies and our skaters sections.
get.matchup.data = function(data, goalie, skater) {
subset(data, goalie_name == goalie & skater_name == skater)
}
We’ve now written our generic data handling functions.
Let’s first start with a function to get data for a specific goalie.
get.goalie.data = function(data, name) {
subset(data, goalie_name == name)
}
Let’s first start with a function to get data for a specific skater.
get.skater.data = function(data, name) {
subset(data, skater_name == name)
}
Given specific data, we should be able to graph the location of shots. Let’s write a function that uses ggplot to do so.
graph.shot.locations = function(data, primary, secondary, name) {
plot = ggplot(data) +
geom_hex(aes(x = x, y = y, alpha = log(..count..)), fill = primary, color = secondary) +
labs(title = paste(name, "Shot Locations", sep = " "), x = "X Position", y = "Y Position") +
theme_minimal()
plot
}
To see a test of what this does, let’s quickly make a graph of Roberto Luongo’s shots against him.
luongo = get.goalie.data(analysis.2017, "Roberto Luongo")
plot = graph.shot.locations(luongo, "#041E42", "#C8102E", "Roberto Luongo")
plot
Now, let’s see how it looks for a skater. Let’s look at Bryan Rust.
rust = get.skater.data(analysis.2017, "Bryan Rust")
plot = graph.shot.locations(rust, "#000000", "#FCB514", "Bryan Rust")
plot
Furthermore, we should be able to graph trends in certain statistics.
graph.trend = function(trend, type, primary, secondary, name) {
frame = data.frame(x = c(1:length(trend)), y = trend)
disp = paste(name, type, "by Game", sep = " ")
plot = ggplot(frame) +
geom_point(aes(x = x, y = y), color = primary) +
geom_smooth(aes(x = x, y = y), method = "lm", color = primary, fill = secondary) +
labs(title = disp, x = "Game Played", y = type) +
theme_minimal()
plot
}
So, let’s go back to Luongo and look at his save percentage per game.
luongo.game.sp = get.game.save.percent(luongo)
plot = graph.trend(luongo.game.sp, "Save Percentage", "#041E42", "#C8102E", "Roberto Luongo")
plot
We can also see the shooter’s perspective. Let’s look at Rust’s shooting percentage (goal percent).
rust.game.gp = get.game.goal.percent(rust)
plot = graph.trend(rust.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Bryan Rust")
plot
Matt Murray is a 24 year old phenomenon who has already won 2 Stanley Cups. Let’s take a look at how he’s done it.
murray.2015 = get.goalie.data(analysis.2015, "Matt Murray")
murray.2016 = get.goalie.data(analysis.2016, "Matt Murray")
murray.2017 = get.goalie.data(analysis.2017, "Matt Murray")
murray.2018 = get.goalie.data(analysis.2018, "Matt Murray")
Let’s start by calculating some of his stats for each season and then tabularizing.
murray.2015.sp = get.save.percent(murray.2015)
murray.2016.sp = get.save.percent(murray.2016)
murray.2017.sp = get.save.percent(murray.2017)
murray.2018.sp = get.save.percent(murray.2018)
murray.2015.gp = get.goal.percent(murray.2015)
murray.2016.gp = get.goal.percent(murray.2016)
murray.2017.gp = get.goal.percent(murray.2017)
murray.2018.gp = get.goal.percent(murray.2018)
murray.2015.spg = get.shots.per.goal(murray.2015)
murray.2016.spg = get.shots.per.goal(murray.2016)
murray.2017.spg = get.shots.per.goal(murray.2017)
murray.2018.spg = get.shots.per.goal(murray.2018)
Now, let’s put it in a table:
| Season | Save Percent | Goal Percent | Shots Per Goal |
|---|---|---|---|
| 2015-2016 | 0.9460043 | 0.0539957 | 18.52 |
| 2016-2017 | 0.9429599 | 0.0570401 | 17.5315315 |
| 2017-2018 | 0.9301837 | 0.0698163 | 14.3233083 |
| 2018-2019 | 0.9335378 | 0.0664622 | 15.0461538 |
We can look at his game by game data also.
murray.2015.games.sp = get.game.save.percent(murray.2015)
murray.2015.games.gp = get.game.goal.percent(murray.2015)
murray.2015.games.spg = get.game.shots.per.goal(murray.2015)
murray.2016.games.sp = get.game.save.percent(murray.2016)
murray.2016.games.gp = get.game.goal.percent(murray.2016)
murray.2016.games.spg = get.game.shots.per.goal(murray.2016)
murray.2017.games.sp = get.game.save.percent(murray.2017)
murray.2017.games.gp = get.game.goal.percent(murray.2017)
murray.2017.games.spg = get.game.shots.per.goal(murray.2017)
murray.2018.games.sp = get.game.save.percent(murray.2018)
murray.2018.games.gp = get.game.goal.percent(murray.2018)
murray.2018.games.spg = get.game.shots.per.goal(murray.2018)
Let’s look at his save percentage graphs:
murray.2015.sp.plot = graph.trend(murray.2015.games.sp, "Save Percentage", "#000000", "#FCB514", "Matt Murray (2015)")
murray.2015.sp.plot
murray.2016.sp.plot = graph.trend(murray.2016.games.sp, "Save Percentage", "#000000", "#FCB514", "Matt Murray (2016)")
murray.2016.sp.plot
murray.2017.sp.plot = graph.trend(murray.2017.games.sp, "Save Percentage", "#000000", "#FCB514", "Matt Murray (2017)")
murray.2017.sp.plot
murray.2018.sp.plot = graph.trend(murray.2018.games.sp, "Save Percentage", "#000000", "#FCB514", "Matt Murray (2018)")
murray.2018.sp.plot
And now, let’s take a look at his shot location data.
murray.2015.locations.plot = graph.shot.locations(murray.2015, "#000000", "#FCB514", "Matt Murray (2015)")
murray.2015.locations.plot
murray.2016.locations.plot = graph.shot.locations(murray.2016, "#000000", "#FCB514", "Matt Murray (2016)")
murray.2016.locations.plot
murray.2017.locations.plot = graph.shot.locations(murray.2017, "#000000", "#FCB514", "Matt Murray (2017)")
murray.2017.locations.plot
murray.2018.locations.plot = graph.shot.locations(murray.2018, "#000000", "#FCB514", "Matt Murray (2018)")
murray.2018.locations.plot
From the darkness of each hex bin, we can use that as a percent chance that Murray saved the shot. Though the darkness is not exactly the save percentage of the shots, it’s the log chance of Murray seeing the shot. This log chance is a good likelihood function of Murray saving the shot. We can see that Murray’s weakness is very close to him. Those shots are most likely to be tipped or deflected shots, not actual shots. We can see his weakness is the top of the circles, based on the X and Y coordinates.
From the graph, we can see that Murray has struggled with shots near the circles. Disregarding tips, it seems like that Murray is positionally sound with goals against near him. However, compared to the right wing, Murray seems weak against shots coming from the left wing side. If teams were to exploit this, it would be beneficial to shoot towards Murray’s glove side from the left wing circle.
On January 11th, Casey DeSmith inked a 3 year extension with the Penguins with an average annual value of $1.25 million. His rise to earn this paycheck started with exemplary play during the 2017-2018 season and that has carried over into this season. Let’s see how he got here!
desmith.2017 = get.goalie.data(analysis.2017, "Casey DeSmith")
desmith.2018 = get.goalie.data(analysis.2018, "Casey DeSmith")
Let’s start by calculating some of his stats for each season and then tabularizing.
desmith.2017.sp = get.save.percent(desmith.2017)
desmith.2018.sp = get.save.percent(desmith.2018)
desmith.2017.gp = get.goal.percent(desmith.2017)
desmith.2018.gp = get.goal.percent(desmith.2018)
desmith.2017.spg = get.shots.per.goal(desmith.2017)
desmith.2018.spg = get.shots.per.goal(desmith.2018)
Now, let’s put it in a table:
| Season | Save Percent | Goal Percent | Shots Per Goal |
|---|---|---|---|
| 2017-2018 | 0.9427403 | 0.0572597 | 17.4642857 |
| 2018-2019 | 0.9371534 | 0.0628466 | 15.9117647 |
We can look at his game by game data also.
desmith.2017.games.sp = get.game.save.percent(desmith.2017)
desmith.2017.games.gp = get.game.goal.percent(desmith.2017)
desmith.2017.games.spg = get.game.shots.per.goal(desmith.2017)
desmith.2018.games.sp = get.game.save.percent(desmith.2018)
desmith.2018.games.gp = get.game.goal.percent(desmith.2018)
desmith.2018.games.spg = get.game.shots.per.goal(desmith.2018)
Let’s look at his save percentage graphs:
desmith.2017.sp.plot = graph.trend(desmith.2017.games.sp, "Save Percentage", "#000000", "#FCB514", "Casey DeSmith (2017)")
desmith.2017.sp.plot
desmith.2018.sp.plot = graph.trend(desmith.2018.games.sp, "Save Percentage", "#000000", "#FCB514", "Casey DeSmith(2018)")
desmith.2018.sp.plot
And now, let’s take a look at his shot location data.
desmith.2017.locations.plot = graph.shot.locations(desmith.2017, "#000000", "#FCB514", "Casey DeSmith (2017)")
desmith.2017.locations.plot
desmith.2018.locations.plot = graph.shot.locations(desmith.2018, "#000000", "#FCB514", "Casey DeSmith (2018)")
desmith.2018.locations.plot
As we can see, DeSmith has played pretty phenomenally. He’s earned his new extension and his play has been pretty consistent. He is the perfect complement for Matt Murray.
Before he was picked by the Vegas Golden Knights in the most recent NHL Expansion Draft, Marc-Andre Fleury was the franchise goaltender for the Pittsburgh Penguins. Drafted first overall in the 2003 NHL Entry Draft, Marc-Andre “Flower” Fleury made his NHL debut in October of 2003. Since thenm he’s been the main net-protector for the Penguins (until 2017 that is). His athleticism plus is exceptionally quick reactions makes Flower a premier NHL goaltender. With 3 Stanley Cup victories (2009, 2016, and 2017), Fleury has cemented his place as a top-10 all-time goaltender. With 429 regular season wins, Fleury sits at number 9 for career regular season wins. Only two active goaltenders, Roberto Luongo and Henrik Lundqvist, sit higher above him.
Fleury has been playing phenomenally the past few season. What seems like a second-prime for the Canadian born goaltender, Fleury showed shades of his 2008-2009 season, when he led the Penguins to their third Stanley Cup
fleury.2015 = get.goalie.data(analysis.2015, "Marc-Andre Fleury")
fleury.2016 = get.goalie.data(analysis.2016, "Marc-Andre Fleury")
fleury.2017 = get.goalie.data(analysis.2017, "Marc-Andre Fleury")
fleury.2018 = get.goalie.data(analysis.2018, "Marc-Andre Fleury")
Let’s start by calculating some of his stats for each season and then tabularizing.
fleury.2015.sp = get.save.percent(fleury.2015)
fleury.2016.sp = get.save.percent(fleury.2016)
fleury.2017.sp = get.save.percent(fleury.2017)
fleury.2018.sp = get.save.percent(fleury.2018)
fleury.2015.gp = get.goal.percent(fleury.2015)
fleury.2016.gp = get.goal.percent(fleury.2016)
fleury.2017.gp = get.goal.percent(fleury.2017)
fleury.2018.gp = get.goal.percent(fleury.2018)
fleury.2015.spg = get.shots.per.goal(fleury.2015)
fleury.2016.spg = get.shots.per.goal(fleury.2016)
fleury.2017.spg = get.shots.per.goal(fleury.2017)
fleury.2018.spg = get.shots.per.goal(fleury.2018)
Now, let’s put it in a table:
| Season | Save Percent | Goal Percent | Shots Per Goal |
|---|---|---|---|
| 2015-2016 | 0.9427197 | 0.0572803 | 17.4580153 |
| 2016-2017 | 0.9314803 | 0.0685197 | 14.5943396 |
| 2017-2018 | 0.9475891 | 0.0524109 | 19.08 |
| 2018-2019 | 0.9348079 | 0.0651921 | 15.3392857 |
We can look at his game by game data also.
fleury.2015.games.sp = get.game.save.percent(fleury.2015)
fleury.2015.games.gp = get.game.goal.percent(fleury.2015)
fleury.2015.games.spg = get.game.shots.per.goal(fleury.2015)
fleury.2016.games.sp = get.game.save.percent(fleury.2016)
fleury.2016.games.gp = get.game.goal.percent(fleury.2016)
fleury.2016.games.spg = get.game.shots.per.goal(fleury.2016)
fleury.2017.games.sp = get.game.save.percent(fleury.2017)
fleury.2017.games.gp = get.game.goal.percent(fleury.2017)
fleury.2017.games.spg = get.game.shots.per.goal(fleury.2017)
fleury.2018.games.sp = get.game.save.percent(fleury.2018)
fleury.2018.games.gp = get.game.goal.percent(fleury.2018)
fleury.2018.games.spg = get.game.shots.per.goal(fleury.2018)
Let’s look at his save percentage graphs:
fleury.2015.sp.plot = graph.trend(fleury.2015.games.sp, "Save Percentage", "#000000", "#FCB514", "Marc-Andre Fleury (2015)")
fleury.2015.sp.plot
fleury.2016.sp.plot = graph.trend(fleury.2016.games.sp, "Save Percentage", "#000000", "#FCB514", "Marc-Andre Fleury (2016)")
fleury.2016.sp.plot
fleury.2017.sp.plot = graph.trend(fleury.2017.games.sp, "Save Percentage", "#B4975A", "#333F42", "Marc-Andre Fleury (2017)")
fleury.2017.sp.plot
fleury.2018.sp.plot = graph.trend(fleury.2018.games.sp, "Save Percentage", "#B4975A", "#333F42", "Marc-Andre Fleury (2018)")
fleury.2018.sp.plot
And now, let’s take a look at his shot location data.
fleury.2015.locations.plot = graph.shot.locations(fleury.2015, "#000000", "#FCB514", "Marc-Andre Fleury (2015)")
fleury.2015.locations.plot
fleury.2016.locations.plot = graph.shot.locations(fleury.2016, "#000000", "#FCB514", "Marc-Andre Fleury (2016)")
fleury.2016.locations.plot
fleury.2017.locations.plot = graph.shot.locations(fleury.2017, "#B4975A", "#333F42", "Marc-Andre Fleury (2017)")
fleury.2017.locations.plot
fleury.2018.locations.plot = graph.shot.locations(fleury.2018, "#B4975A", "#333F42", "Marc-Andre Fleury (2018)")
fleury.2018.locations.plot
Fleury has shown exceptional consistency. For any young goaltender breaking into the league, he should be a top-role model.
After exercising his playoff demons during the 2018 Stanley Cup Playoffs, Braden Holtby has lived up to his expectations. His play has been phenomenal during both the regular season and playoffs. Let’s see how he’s been since 2015.
holtby.2015 = get.goalie.data(analysis.2015, "Braden Holtby")
holtby.2016 = get.goalie.data(analysis.2016, "Braden Holtby")
holtby.2017 = get.goalie.data(analysis.2017, "Braden Holtby")
holtby.2018 = get.goalie.data(analysis.2018, "Braden Holtby")
Let’s start by calculating some of his stats for each season and then tabularizing.
holtby.2015.sp = get.save.percent(holtby.2015)
holtby.2016.sp = get.save.percent(holtby.2016)
holtby.2017.sp = get.save.percent(holtby.2017)
holtby.2018.sp = get.save.percent(holtby.2018)
holtby.2015.gp = get.goal.percent(holtby.2015)
holtby.2016.gp = get.goal.percent(holtby.2016)
holtby.2017.gp = get.goal.percent(holtby.2017)
holtby.2018.gp = get.goal.percent(holtby.2018)
holtby.2015.spg = get.shots.per.goal(holtby.2015)
holtby.2016.spg = get.shots.per.goal(holtby.2016)
holtby.2017.spg = get.shots.per.goal(holtby.2017)
holtby.2018.spg = get.shots.per.goal(holtby.2018)
Now, let’s put it in a table:
| Season | Save Percent | Goal Percent | Shots Per Goal |
|---|---|---|---|
| 2015-2016 | 0.9448141 | 0.0551859 | 18.1205674 |
| 2016-2017 | 0.9476936 | 0.0523064 | 19.1181102 |
| 2017-2018 | 0.9348104 | 0.0651896 | 15.3398693 |
| 2018-2019 | 0.9311957 | 0.0688043 | 14.5339806 |
We can look at his game by game data also.
holtby.2015.games.sp = get.game.save.percent(holtby.2015)
holtby.2015.games.gp = get.game.goal.percent(holtby.2015)
holtby.2015.games.spg = get.game.shots.per.goal(holtby.2015)
holtby.2016.games.sp = get.game.save.percent(holtby.2016)
holtby.2016.games.gp = get.game.goal.percent(holtby.2016)
holtby.2016.games.spg = get.game.shots.per.goal(holtby.2016)
holtby.2017.games.sp = get.game.save.percent(holtby.2017)
holtby.2017.games.gp = get.game.goal.percent(holtby.2017)
holtby.2017.games.spg = get.game.shots.per.goal(holtby.2017)
holtby.2018.games.sp = get.game.save.percent(holtby.2018)
holtby.2018.games.gp = get.game.goal.percent(holtby.2018)
holtby.2018.games.spg = get.game.shots.per.goal(holtby.2018)
Let’s look at his save percentage graphs:
holtby.2015.sp.plot = graph.trend(holtby.2015.games.sp, "Save Percentage", "#041E42", "#C8102E", "Braden Holtby (2015)")
holtby.2015.sp.plot
holtby.2016.sp.plot = graph.trend(holtby.2016.games.sp, "Save Percentage", "#041E42", "#C8102E", "Braden Holtby (2016)")
holtby.2016.sp.plot
holtby.2017.sp.plot = graph.trend(holtby.2017.games.sp, "Save Percentage", "#041E42", "#C8102E", "Braden Holtby (2017)")
holtby.2017.sp.plot
holtby.2018.sp.plot = graph.trend(holtby.2018.games.sp, "Save Percentage", "#041E42", "#C8102E", "Braden Holtby (2018)")
holtby.2018.sp.plot
And now, let’s take a look at his shot location data.
holtby.2015.locations.plot = graph.shot.locations(holtby.2015, "#041E42", "#C8102E", "Braden Holtby (2015)")
holtby.2015.locations.plot
holtby.2016.locations.plot = graph.shot.locations(holtby.2016, "#041E42", "#C8102E", "Braden Holtby (2016)")
holtby.2016.locations.plot
holtby.2017.locations.plot = graph.shot.locations(holtby.2017, "#041E42", "#C8102E", "Braden Holtby (2017)")
holtby.2017.locations.plot
holtby.2018.locations.plot = graph.shot.locations(holtby.2018, "#041E42", "#C8102E", "Braden Holtby (2018)")
holtby.2018.locations.plot
Holtby has had the trend of playing poorly near the end of the season. However, it seems like Holtby is currently going against his negative trend this season. His main weakness seems to be shots from the left circle. This is probably aimed towards his glove hand, which is significantly weaker than his positional play.
Hailing from Pittsburgh Pennsylvania, John Gibson is the 25-year-old starter for the Anaheim Ducks. In his 6 years in the NHL, Gibson has played a total of 221 games, starting 213 games. In his career, Gibson boasts a 2.37 GAA and 92.2% save percentage. Let’s start by looking at his growth per season.
gibson.2015 = get.goalie.data(analysis.2015, "John Gibson")
gibson.2016 = get.goalie.data(analysis.2016, "John Gibson")
gibson.2017 = get.goalie.data(analysis.2017, "John Gibson")
gibson.2018 = get.goalie.data(analysis.2018, "John Gibson")
Let’s start by calculating some of his stats for each season and then tabularizing.
gibson.2015.sp = get.save.percent(gibson.2015)
gibson.2016.sp = get.save.percent(gibson.2016)
gibson.2017.sp = get.save.percent(gibson.2017)
gibson.2018.sp = get.save.percent(gibson.2018)
gibson.2015.gp = get.goal.percent(gibson.2015)
gibson.2016.gp = get.goal.percent(gibson.2016)
gibson.2017.gp = get.goal.percent(gibson.2017)
gibson.2018.gp = get.goal.percent(gibson.2018)
gibson.2015.spg = get.shots.per.goal(gibson.2015)
gibson.2016.spg = get.shots.per.goal(gibson.2016)
gibson.2017.spg = get.shots.per.goal(gibson.2017)
gibson.2018.spg = get.shots.per.goal(gibson.2018)
Now, let’s put it in a table:
| Season | Save Percent | Goal Percent | Shots Per Goal |
|---|---|---|---|
| 2015-2016 | 0.9439319 | 0.0560681 | 17.835443 |
| 2016-2017 | 0.9456901 | 0.0543099 | 18.412844 |
| 2017-2018 | 0.948018 | 0.051982 | 19.2374101 |
| 2018-2019 | 0.9419087 | 0.0580913 | 17.2142857 |
We can look at his game by game data also.
gibson.2015.games.sp = get.game.save.percent(gibson.2015)
gibson.2015.games.gp = get.game.goal.percent(gibson.2015)
gibson.2015.games.spg = get.game.shots.per.goal(gibson.2015)
gibson.2016.games.sp = get.game.save.percent(gibson.2016)
gibson.2016.games.gp = get.game.goal.percent(gibson.2016)
gibson.2016.games.spg = get.game.shots.per.goal(gibson.2016)
gibson.2017.games.sp = get.game.save.percent(gibson.2017)
gibson.2017.games.gp = get.game.goal.percent(gibson.2017)
gibson.2017.games.spg = get.game.shots.per.goal(gibson.2017)
gibson.2018.games.sp = get.game.save.percent(gibson.2018)
gibson.2018.games.gp = get.game.goal.percent(gibson.2018)
gibson.2018.games.spg = get.game.shots.per.goal(gibson.2018)
Let’s look at his save percentage graphs:
gibson.2015.sp.plot = graph.trend(gibson.2015.games.sp, "Save Percentage", "#F47A38", "#B09862", "John Gibson (2015)")
gibson.2015.sp.plot
gibson.2016.sp.plot = graph.trend(gibson.2016.games.sp, "Save Percentage", "#F47A38", "#B09862", "John Gibson (2016)")
gibson.2016.sp.plot
gibson.2017.sp.plot = graph.trend(gibson.2017.games.sp, "Save Percentage", "#F47A38", "#B09862", "John Gibson (2017)")
gibson.2017.sp.plot
gibson.2018.sp.plot = graph.trend(gibson.2018.games.sp, "Save Percentage", "#F47A38", "#B09862", "John Gibson (2018)")
gibson.2018.sp.plot
And now, let’s take a look at his shot location data.
gibson.2015.locations.plot = graph.shot.locations(gibson.2015, "#F47A38", "#B09862", "John Gibson (2015)")
gibson.2015.locations.plot
gibson.2016.locations.plot = graph.shot.locations(gibson.2016, "#F47A38", "#B09862", "John Gibson (2016)")
gibson.2016.locations.plot
gibson.2017.locations.plot = graph.shot.locations(gibson.2017, "#F47A38", "#B09862", "John Gibson (2017)")
gibson.2017.locations.plot
gibson.2018.locations.plot = graph.shot.locations(gibson.2018, "#F47A38", "#B09862", "John Gibson (2018)")
gibson.2018.locations.plot
Already regarded as being in the top 5 all-time greatest NHL players, Sidney Crosby has been playing like an MVP for every single season he’s been in the league. Let’s look at his past few seasons in more detail.
crosby.2015 = get.skater.data(analysis.2015, "Sidney Crosby")
crosby.2016 = get.skater.data(analysis.2016, "Sidney Crosby")
crosby.2017 = get.skater.data(analysis.2017, "Sidney Crosby")
crosby.2018 = get.skater.data(analysis.2018, "Sidney Crosby")
Let’s get some of his stats.
crosby.2015.sp = get.save.percent(crosby.2015)
crosby.2015.game.sp = get.game.save.percent(crosby.2015)
crosby.2016.sp = get.save.percent(crosby.2016)
crosby.2016.game.sp = get.game.save.percent(crosby.2016)
crosby.2017.sp = get.save.percent(crosby.2017)
crosby.2017.game.sp = get.game.save.percent(crosby.2017)
crosby.2018.sp = get.save.percent(crosby.2018)
crosby.2018.game.sp = get.game.save.percent(crosby.2018)
crosby.2015.gp = get.goal.percent(crosby.2015)
crosby.2015.game.gp = get.game.goal.percent(crosby.2015)
crosby.2016.gp = get.goal.percent(crosby.2016)
crosby.2016.game.gp = get.game.goal.percent(crosby.2016)
crosby.2017.gp = get.goal.percent(crosby.2017)
crosby.2017.game.gp = get.game.goal.percent(crosby.2017)
crosby.2018.gp = get.goal.percent(crosby.2018)
crosby.2018.game.gp = get.game.goal.percent(crosby.2018)
crosby.2015.spg = get.shots.per.goal(crosby.2015)
crosby.2015.game.spg = get.game.shots.per.goal(crosby.2015)
crosby.2016.spg = get.shots.per.goal(crosby.2016)
crosby.2016.game.spg = get.game.shots.per.goal(crosby.2016)
crosby.2017.spg = get.shots.per.goal(crosby.2017)
crosby.2017.game.spg = get.game.shots.per.goal(crosby.2017)
crosby.2018.spg = get.shots.per.goal(crosby.2018)
crosby.2018.game.spg = get.game.shots.per.goal(crosby.2018)
Here’s a table of his data.
| Season | Save Percent | Goal Percent | Shots per Goal |
|---|---|---|---|
| 2015-2016 | 0.8947368 | 0.1052632 | 9.5 |
| 2016-2017 | 0.8646154 | 0.1353846 | 7.3863636 |
| 2017-2018 | 0.914956 | 0.085044 | 11.7586207 |
| 2018-2019 | 0.8826816 | 0.1173184 | 8.5238095 |
Let’s take a look at his heatmaps.
crosby.2015.locations.plot = graph.shot.locations(crosby.2015, "#000000", "#FCB514", "Sidney Crosby (2015)")
crosby.2015.locations.plot
crosby.2016.locations.plot = graph.shot.locations(crosby.2016, "#000000", "#FCB514", "Sidney Crosby (2016)")
crosby.2016.locations.plot
crosby.2017.locations.plot = graph.shot.locations(crosby.2017, "#000000", "#FCB514", "Sidney Crosby (2017)")
crosby.2017.locations.plot
crosby.2018.locations.plot = graph.shot.locations(crosby.2018, "#000000", "#FCB514", "Sidney Crosby (2018)")
crosby.2018.locations.plot
From this, we can see that Sidney Crosby has a lot of success around the net. Let’s look at this goal percentage per game now.
crosby.2015.gp.plot = graph.trend(crosby.2015.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Sidney Crosby (2015)")
crosby.2015.gp.plot
crosby.2016.gp.plot = graph.trend(crosby.2016.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Sidney Crosby (2016)")
crosby.2016.gp.plot
crosby.2017.gp.plot = graph.trend(crosby.2017.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Sidney Crosby (2017)")
crosby.2017.gp.plot
crosby.2018.gp.plot = graph.trend(crosby.2018.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Sidney Crosby (2018)")
crosby.2018.gp.plot
A clear elite first line center, Evgeni Malkin has played behind Sidney Crosby his entire career. However, instead of fussing out this, he puts up first line center numbers every year. Let’s see how he’s done it his previous few years.
malkin.2015 = get.skater.data(analysis.2015, "Evgeni Malkin")
malkin.2016 = get.skater.data(analysis.2016, "Evgeni Malkin")
malkin.2017 = get.skater.data(analysis.2017, "Evgeni Malkin")
malkin.2018 = get.skater.data(analysis.2018, "Evgeni Malkin")
Let’s get some of his stats.
malkin.2015.sp = get.save.percent(malkin.2015)
malkin.2015.game.sp = get.game.save.percent(malkin.2015)
malkin.2016.sp = get.save.percent(malkin.2016)
malkin.2016.game.sp = get.game.save.percent(malkin.2016)
malkin.2017.sp = get.save.percent(malkin.2017)
malkin.2017.game.sp = get.game.save.percent(malkin.2017)
malkin.2018.sp = get.save.percent(malkin.2018)
malkin.2018.game.sp = get.game.save.percent(malkin.2018)
malkin.2015.gp = get.goal.percent(malkin.2015)
malkin.2015.game.gp = get.game.goal.percent(malkin.2015)
malkin.2016.gp = get.goal.percent(malkin.2016)
malkin.2016.game.gp = get.game.goal.percent(malkin.2016)
malkin.2017.gp = get.goal.percent(malkin.2017)
malkin.2017.game.gp = get.game.goal.percent(malkin.2017)
malkin.2018.gp = get.goal.percent(malkin.2018)
malkin.2018.game.gp = get.game.goal.percent(malkin.2018)
malkin.2015.spg = get.shots.per.goal(malkin.2015)
malkin.2015.game.spg = get.game.shots.per.goal(malkin.2015)
malkin.2016.spg = get.shots.per.goal(malkin.2016)
malkin.2016.game.spg = get.game.shots.per.goal(malkin.2016)
malkin.2017.spg = get.shots.per.goal(malkin.2017)
malkin.2017.game.spg = get.game.shots.per.goal(malkin.2017)
malkin.2018.spg = get.shots.per.goal(malkin.2018)
malkin.2018.game.spg = get.game.shots.per.goal(malkin.2018)
Here’s a table of his data.
| Season | Save Percent | Goal Percent | Shots per Goal |
|---|---|---|---|
| 2015-2016 | 0.8767123 | 0.1232877 | 8.1111111 |
| 2016-2017 | 0.8674699 | 0.1325301 | 7.5454545 |
| 2017-2018 | 0.8622951 | 0.1377049 | 7.2619048 |
| 2018-2019 | 0.9186047 | 0.0813953 | 12.2857143 |
Let’s take a look at his heatmaps.
malkin.2015.locations.plot = graph.shot.locations(malkin.2015, "#000000", "#FCB514", "Evgeni Malkin (2015)")
malkin.2015.locations.plot
malkin.2016.locations.plot = graph.shot.locations(malkin.2016, "#000000", "#FCB514", "Evgeni Malkin (2016)")
malkin.2016.locations.plot
malkin.2017.locations.plot = graph.shot.locations(malkin.2017, "#000000", "#FCB514", "Evgeni Malkin (2017)")
malkin.2017.locations.plot
malkin.2018.locations.plot = graph.shot.locations(malkin.2018, "#000000", "#FCB514", "Evgeni Malkin (2018)")
malkin.2018.locations.plot
Let’s look at this goal percentage per game now.
malkin.2015.gp.plot = graph.trend(malkin.2015.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Evgeni Malkin (2015)")
malkin.2015.gp.plot
malkin.2016.gp.plot = graph.trend(malkin.2016.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Evgeni Malkin (2016)")
malkin.2016.gp.plot
malkin.2017.gp.plot = graph.trend(malkin.2017.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Evgeni Malkin (2017)")
malkin.2017.gp.plot
malkin.2018.gp.plot = graph.trend(malkin.2018.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Evgeni Malkin (2018)")
malkin.2018.gp.plot
Alexander Ovechkin’s style of play is simply eletric. With an extremely hard and accurate slap shot mixed in with a deadly quick wrist shot, Ovechkin is a scoring machine. The Russian-born winger has cemented himself as one of the best Russians to ever play in the NHL.
ovechkin.2015 = get.skater.data(analysis.2015, "Alex Ovechkin")
ovechkin.2016 = get.skater.data(analysis.2016, "Alex Ovechkin")
ovechkin.2017 = get.skater.data(analysis.2017, "Alex Ovechkin")
ovechkin.2018 = get.skater.data(analysis.2018, "Alex Ovechkin")
Let’s get some of his stats.
ovechkin.2015.sp = get.save.percent(ovechkin.2015)
ovechkin.2015.game.sp = get.game.save.percent(ovechkin.2015)
ovechkin.2016.sp = get.save.percent(ovechkin.2016)
ovechkin.2016.game.sp = get.game.save.percent(ovechkin.2016)
ovechkin.2017.sp = get.save.percent(ovechkin.2017)
ovechkin.2017.game.sp = get.game.save.percent(ovechkin.2017)
ovechkin.2018.sp = get.save.percent(ovechkin.2018)
ovechkin.2018.game.sp = get.game.save.percent(ovechkin.2018)
ovechkin.2015.gp = get.goal.percent(ovechkin.2015)
ovechkin.2015.game.gp = get.game.goal.percent(ovechkin.2015)
ovechkin.2016.gp = get.goal.percent(ovechkin.2016)
ovechkin.2016.game.gp = get.game.goal.percent(ovechkin.2016)
ovechkin.2017.gp = get.goal.percent(ovechkin.2017)
ovechkin.2017.game.gp = get.game.goal.percent(ovechkin.2017)
ovechkin.2018.gp = get.goal.percent(ovechkin.2018)
ovechkin.2018.game.gp = get.game.goal.percent(ovechkin.2018)
ovechkin.2015.spg = get.shots.per.goal(ovechkin.2015)
ovechkin.2015.game.spg = get.game.shots.per.goal(ovechkin.2015)
ovechkin.2016.spg = get.shots.per.goal(ovechkin.2016)
ovechkin.2016.game.spg = get.game.shots.per.goal(ovechkin.2016)
ovechkin.2017.spg = get.shots.per.goal(ovechkin.2017)
ovechkin.2017.game.spg = get.game.shots.per.goal(ovechkin.2017)
ovechkin.2018.spg = get.shots.per.goal(ovechkin.2018)
ovechkin.2018.game.spg = get.game.shots.per.goal(ovechkin.2018)
Here’s a table of his data.
| Season | Save Percent | Goal Percent | Shots per Goal |
|---|---|---|---|
| 2015-2016 | 0.9111901 | 0.0888099 | 11.26 |
| 2016-2017 | 0.9274725 | 0.0725275 | 13.7878788 |
| 2017-2018 | 0.9068441 | 0.0931559 | 10.7346939 |
| 2018-2019 | 0.8778878 | 0.1221122 | 8.1891892 |
Let’s take a look at his heatmaps.
ovechkin.2015.locations.plot = graph.shot.locations(ovechkin.2015, "#041E42", "#C8102E", "Alex Ovechkin (2015)")
ovechkin.2015.locations.plot
ovechkin.2016.locations.plot = graph.shot.locations(ovechkin.2016, "#041E42", "#C8102E", "Alex Ovechkin (2016)")
ovechkin.2016.locations.plot
ovechkin.2017.locations.plot = graph.shot.locations(ovechkin.2017, "#041E42", "#C8102E", "Alex Ovechkin (2017)")
ovechkin.2017.locations.plot
ovechkin.2018.locations.plot = graph.shot.locations(ovechkin.2018, "#041E42", "#C8102E", "Alex Ovechkin (2018)")
ovechkin.2018.locations.plot
Let’s look at this goal percentage per game now.
ovechkin.2015.gp.plot = graph.trend(ovechkin.2015.game.gp, "Shooting (Goal) Percentage", "#041E42", "#C8102E", "Alex Ovechkin (2015)")
ovechkin.2015.gp.plot
ovechkin.2016.gp.plot = graph.trend(ovechkin.2016.game.gp, "Shooting (Goal) Percentage", "#041E42", "#C8102E", "Alex Ovechkin (2016)")
ovechkin.2016.gp.plot
ovechkin.2017.gp.plot = graph.trend(ovechkin.2017.game.gp, "Shooting (Goal) Percentage", "#041E42", "#C8102E", "Alex Ovechkin (2017)")
ovechkin.2017.gp.plot
ovechkin.2018.gp.plot = graph.trend(ovechkin.2018.game.gp, "Shooting (Goal) Percentage", "#041E42", "#C8102E", "Alex Ovechkin (2018)")
ovechkin.2018.gp.plot
Jake Guentzel has been an elite farm-system talent for the Penguins.
guentzel.2016 = get.skater.data(analysis.2016, "Jake Guentzel")
guentzel.2017 = get.skater.data(analysis.2017, "Jake Guentzel")
guentzel.2018 = get.skater.data(analysis.2018, "Jake Guentzel")
Let’s get some of his stats.
guentzel.2016.sp = get.save.percent(guentzel.2016)
guentzel.2016.game.sp = get.game.save.percent(guentzel.2016)
guentzel.2017.sp = get.save.percent(guentzel.2017)
guentzel.2017.game.sp = get.game.save.percent(guentzel.2017)
guentzel.2018.sp = get.save.percent(guentzel.2018)
guentzel.2018.game.sp = get.game.save.percent(guentzel.2018)
guentzel.2016.gp = get.goal.percent(guentzel.2016)
guentzel.2016.game.gp = get.game.goal.percent(guentzel.2016)
guentzel.2017.gp = get.goal.percent(guentzel.2017)
guentzel.2017.game.gp = get.game.goal.percent(guentzel.2017)
guentzel.2018.gp = get.goal.percent(guentzel.2018)
guentzel.2018.game.gp = get.game.goal.percent(guentzel.2018)
guentzel.2016.spg = get.shots.per.goal(guentzel.2016)
guentzel.2016.game.spg = get.game.shots.per.goal(guentzel.2016)
guentzel.2017.spg = get.shots.per.goal(guentzel.2017)
guentzel.2017.game.spg = get.game.shots.per.goal(guentzel.2017)
guentzel.2018.spg = get.shots.per.goal(guentzel.2018)
guentzel.2018.game.spg = get.game.shots.per.goal(guentzel.2018)
Here’s a table of his data.
| Season | Save Percent | Goal Percent | Shots per Goal |
|---|---|---|---|
| 2016-2017 | 0.8518519 | 0.1481481 | 6.75 |
| 2017-2018 | 0.9079498 | 0.0920502 | 10.8636364 |
| 2018-2019 | 0.8688525 | 0.1311475 | 7.625 |
From this data, we can see that Guentzel isn’t a sniper; instead he is a volume shooter. Let’s take a look at his heatmaps.
guentzel.2016.locations.plot = graph.shot.locations(guentzel.2016, "#000000", "#FCB514", "Jake Guentzel (2016)")
guentzel.2016.locations.plot
guentzel.2017.locations.plot = graph.shot.locations(guentzel.2017, "#000000", "#FCB514", "Jake Guentzel (2017)")
guentzel.2017.locations.plot
guentzel.2018.locations.plot = graph.shot.locations(guentzel.2018, "#000000", "#FCB514", "Jake Guentzel (2018)")
guentzel.2018.locations.plot
From this, we can see that Jake Guentzel has a lot of success around the net. Let’s look at this goal percentage per game now.
guentzel.2016.gp.plot = graph.trend(guentzel.2016.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Jake Guentzel (2016)")
guentzel.2016.gp.plot
guentzel.2017.gp.plot = graph.trend(guentzel.2017.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Jake Guentzel (2017)")
guentzel.2017.gp.plot
guentzel.2018.gp.plot = graph.trend(guentzel.2018.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Jake Guentzel (2018)")
guentzel.2018.gp.plot
A Norris Trophy caliber defensemen, Erik Karlsson helped redefined the modern defender. His exceptional speed as well as his quick passing ability has him as a franchise talent.
karlsson.2015 = get.skater.data(analysis.2015, "Erik Karlsson")
karlsson.2016 = get.skater.data(analysis.2016, "Erik Karlsson")
karlsson.2017 = get.skater.data(analysis.2017, "Erik Karlsson")
karlsson.2018 = get.skater.data(analysis.2018, "Erik Karlsson")
Let’s get some of his stats.
karlsson.2015.sp = get.save.percent(karlsson.2015)
karlsson.2015.game.sp = get.game.save.percent(karlsson.2015)
karlsson.2016.sp = get.save.percent(karlsson.2016)
karlsson.2016.game.sp = get.game.save.percent(karlsson.2016)
karlsson.2017.sp = get.save.percent(karlsson.2017)
karlsson.2017.game.sp = get.game.save.percent(karlsson.2017)
karlsson.2018.sp = get.save.percent(karlsson.2018)
karlsson.2018.game.sp = get.game.save.percent(karlsson.2018)
karlsson.2015.gp = get.goal.percent(karlsson.2015)
karlsson.2015.game.gp = get.game.goal.percent(karlsson.2015)
karlsson.2016.gp = get.goal.percent(karlsson.2016)
karlsson.2016.game.gp = get.game.goal.percent(karlsson.2016)
karlsson.2017.gp = get.goal.percent(karlsson.2017)
karlsson.2017.game.gp = get.game.goal.percent(karlsson.2017)
karlsson.2018.gp = get.goal.percent(karlsson.2018)
karlsson.2018.game.gp = get.game.goal.percent(karlsson.2018)
karlsson.2015.spg = get.shots.per.goal(karlsson.2015)
karlsson.2015.game.spg = get.game.shots.per.goal(karlsson.2015)
karlsson.2016.spg = get.shots.per.goal(karlsson.2016)
karlsson.2016.game.spg = get.game.shots.per.goal(karlsson.2016)
karlsson.2017.spg = get.shots.per.goal(karlsson.2017)
karlsson.2017.game.spg = get.game.shots.per.goal(karlsson.2017)
karlsson.2018.spg = get.shots.per.goal(karlsson.2018)
karlsson.2018.game.spg = get.game.shots.per.goal(karlsson.2018)
Here’s a table of his data.
| Season | Save Percent | Goal Percent | Shots per Goal |
|---|---|---|---|
| 2015-2016 | 0.9578947 | 0.0421053 | 23.75 |
| 2016-2017 | 0.9495549 | 0.0504451 | 19.8235294 |
| 2017-2018 | 0.9695946 | 0.0304054 | 32.8888889 |
| 2018-2019 | 0.9868996 | 0.0131004 | 76.3333333 |
Let’s take a look at his heatmaps.
karlsson.2015.locations.plot = graph.shot.locations(karlsson.2015, "#E31837", "#C69214", "Erik Karlsson (2015)")
karlsson.2015.locations.plot
karlsson.2016.locations.plot = graph.shot.locations(karlsson.2016, "#E31837", "#C69214", "Erik Karlsson (2016)")
karlsson.2016.locations.plot
karlsson.2017.locations.plot = graph.shot.locations(karlsson.2017, "#E31837", "#C69214", "Erik Karlsson (2017)")
karlsson.2017.locations.plot
karlsson.2018.locations.plot = graph.shot.locations(karlsson.2018, "#006D75", "#EA7200", "Erik Karlsson (2018)")
karlsson.2018.locations.plot
Let’s look at this goal percentage per game now.
karlsson.2015.gp.plot = graph.trend(karlsson.2015.game.gp, "Shooting (Goal) Percentage", "#E31837", "#C69214", "Erik Karlsson (2015)")
karlsson.2015.gp.plot
karlsson.2016.gp.plot = graph.trend(karlsson.2016.game.gp, "Shooting (Goal) Percentage", "#E31837", "#C69214", "Erik Karlsson (2016)")
karlsson.2016.gp.plot
karlsson.2017.gp.plot = graph.trend(karlsson.2017.game.gp, "Shooting (Goal) Percentage", "#E31837", "#C69214", "Erik Karlsson (2017)")
karlsson.2017.gp.plot
karlsson.2018.gp.plot = graph.trend(karlsson.2018.game.gp, "Shooting (Goal) Percentage", "#006D75", "#EA7200", "Erik Karlsson (2018)")
karlsson.2018.gp.plot
Kris Letang has suffered through many major injuries but still performs like a Norris Trophy winning defensemen. Let’s see his growth through the years.
letang.2015 = get.skater.data(analysis.2015, "Kris Letang")
letang.2016 = get.skater.data(analysis.2016, "Kris Letang")
letang.2017 = get.skater.data(analysis.2017, "Kris Letang")
letang.2018 = get.skater.data(analysis.2018, "Kris Letang")
Let’s get some of his stats.
letang.2015.sp = get.save.percent(letang.2015)
letang.2015.game.sp = get.game.save.percent(letang.2015)
letang.2016.sp = get.save.percent(letang.2016)
letang.2016.game.sp = get.game.save.percent(letang.2016)
letang.2017.sp = get.save.percent(letang.2017)
letang.2017.game.sp = get.game.save.percent(letang.2017)
letang.2018.sp = get.save.percent(letang.2018)
letang.2018.game.sp = get.game.save.percent(letang.2018)
letang.2015.gp = get.goal.percent(letang.2015)
letang.2015.game.gp = get.game.goal.percent(letang.2015)
letang.2016.gp = get.goal.percent(letang.2016)
letang.2016.game.gp = get.game.goal.percent(letang.2016)
letang.2017.gp = get.goal.percent(letang.2017)
letang.2017.game.gp = get.game.goal.percent(letang.2017)
letang.2018.gp = get.goal.percent(letang.2018)
letang.2018.game.gp = get.game.goal.percent(letang.2018)
letang.2015.spg = get.shots.per.goal(letang.2015)
letang.2015.game.spg = get.game.shots.per.goal(letang.2015)
letang.2016.spg = get.shots.per.goal(letang.2016)
letang.2016.game.spg = get.game.shots.per.goal(letang.2016)
letang.2017.spg = get.shots.per.goal(letang.2017)
letang.2017.game.spg = get.game.shots.per.goal(letang.2017)
letang.2018.spg = get.shots.per.goal(letang.2018)
letang.2018.game.spg = get.game.shots.per.goal(letang.2018)
Here’s a table of his data.
| Season | Save Percent | Goal Percent | Shots per Goal |
|---|---|---|---|
| 2015-2016 | 0.9409594 | 0.0590406 | 16.9375 |
| 2016-2017 | 0.9693252 | 0.0306748 | 32.6 |
| 2017-2018 | 0.969697 | 0.030303 | 33 |
| 2018-2019 | 0.9344262 | 0.0655738 | 15.25 |
Let’s take a look at his heatmaps.
letang.2015.locations.plot = graph.shot.locations(letang.2015, "#000000", "#FCB514", "Kris Letang (2015)")
letang.2015.locations.plot
letang.2016.locations.plot = graph.shot.locations(letang.2016, "#000000", "#FCB514", "Kris Letang (2016)")
letang.2016.locations.plot
letang.2017.locations.plot = graph.shot.locations(letang.2017, "#000000", "#FCB514", "Kris Letang (2017)")
letang.2017.locations.plot
letang.2018.locations.plot = graph.shot.locations(letang.2018, "#000000", "#FCB514", "Kris Letang (2018)")
letang.2018.locations.plot
Let’s look at this goal percentage per game now.
letang.2015.gp.plot = graph.trend(letang.2015.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Kris Letang (2015)")
letang.2015.gp.plot
letang.2016.gp.plot = graph.trend(letang.2016.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Kris Letang (2016)")
letang.2016.gp.plot
letang.2017.gp.plot = graph.trend(letang.2017.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Kris Letang (2017)")
letang.2017.gp.plot
letang.2018.gp.plot = graph.trend(letang.2018.game.gp, "Shooting (Goal) Percentage", "#000000", "#FCB514", "Kris Letang (2018)")
letang.2018.gp.plot